package service

import (
	"context"
	"fmt"
	"iris-wms/apps/admin/web/dto/din"
	"iris-wms/apps/admin/web/dto/dout"
	"iris-wms/common/model"
	"iris-wms/common/pkg/db"
	"iris-wms/common/pkg/db/dao"

	"gorm.io/gen"
	"gorm.io/gorm"
)

var _ WmsGoodsService = (*wmsGoodsService)(nil)

type WmsGoodsService interface {
	Create(din.WmsGoodsIn) error
	Update(din.WmsGoodsIn) error
	DeleteByIdList([]uint) error
	GetTable(din.WmsGoodsTableIn) ([]*dout.WmsGoodsOut, int64, error)
	GetList() ([]*dout.WmsGoodsOut, error)
	GetByCode(string) (*dout.WmsGoodsOut, error)
}

func NewWmsGoodsService() *wmsGoodsService {
	return &wmsGoodsService{}
}

type wmsGoodsService struct{}

func (impl *wmsGoodsService) Create(in din.WmsGoodsIn) (err error) {
	err = db.GDB1.Transaction(func(tx *gorm.DB) error {
		if err := tx.Create(&in.Goods).Error; err != nil {
			return err
		}
		for _, v := range in.Images {
			v.GoodsId = in.Goods.ID
		}
		if err := tx.CreateInBatches(&in.Images, 100).Error; err != nil {
			return err
		}
		return nil
	})
	return
}

func (impl *wmsGoodsService) Update(in din.WmsGoodsIn) (err error) {
	for _, v := range in.Images {
		v.GoodsId = in.Goods.ID
	}
	err = db.GDB1.Transaction(func(tx *gorm.DB) error {
		if err := tx.Save(&in.Goods).Error; err != nil {
			return err
		}
		if err = tx.Delete(&model.WmsGoodsImage{}, "goods_id = ?", in.Goods.ID).Error; err != nil {
			return err
		}
		if err := tx.CreateInBatches(&in.Images, 100).Error; err != nil {
			return err
		}
		return nil
	})
	return
}

func (impl *wmsGoodsService) DeleteByIdList(idList []uint) (err error) {
	// TODO 有业务数据，则不能删除
	err = db.GDB1.Transaction(func(tx *gorm.DB) error {
		if err = tx.Delete(&model.WmsGoods{}, "id in ?", idList).Error; err != nil {
			return err
		}
		if err = tx.Delete(&model.WmsGoodsImage{}, "goods_id in ?", idList).Error; err != nil {
			return err
		}
		return nil
	})
	return
}

func (impl *wmsGoodsService) GetTable(in din.WmsGoodsTableIn) (rows []*dout.WmsGoodsOut, total int64, err error) {
	q := dao.Use(db.GDB1).WmsGoodsOut
	do := q.WithContext(context.Background())

	condList := make([]gen.Condition, 0)
	if in.Enable > 0 {
		condList = append(condList, q.Enable.Eq(in.Enable))
	}
	if in.IsGift > 0 {
		condList = append(condList, q.IsGift.Eq(in.IsGift))
	}
	if in.CateId <= 0 {
		condList = append(condList, q.CateId.Gte(0))
	}
	if in.Word != "" {
		word := fmt.Sprintf("%%%s%%", in.Word)
		do = do.
			Where(do.Where(q.Code.Like(word)).
				Or(q.Name.Like(word)).
				Or(q.Barcode.Like(word)))
	}

	rows, total, err = do.Where(condList...).
		Preload(q.Creator).
		Preload(q.Cate).
		Preload(q.Images).
		Order(q.CreatedAt.Desc()).
		FindByPage(in.Offset(), in.PageSize)
	return
}

func (impl *wmsGoodsService) GetList() (rows []*dout.WmsGoodsOut, err error) {
	q := dao.Use(db.GDB1).WmsGoodsOut
	do := q.WithContext(context.Background())

	rows, err = do.Find()
	return
}

func (impl *wmsGoodsService) GetByCode(word string) (result *dout.WmsGoodsOut, err error) {
	q := dao.Use(db.GDB1).WmsGoodsOut
	do := q.WithContext(context.Background()).Preload(q.Cate)
	result, err = do.Or(q.Code.Eq(word)).Or(q.Barcode.Eq(word)).Take()
	return
}
